﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iReaper.IndexService.Common.TaskEngine
{
    public interface ITask
    {
        void Initialize(Queue<EventItem> inputQueue, Queue<EventItem> resultQueue, ITask previous);

        void Close();

        void Done();

        void Start();

        event EventHandler<ProgressEventArgs> OnProgress;

        bool IsComplete { get; }
    }

    public abstract class TaskBase : ITask
    {
        #region field

        private Queue<EventItem> m_outputQueue;
        private Queue<EventItem> m_inputQueue;
        private bool m_isDone = false;
        private ITask m_previous;
        #endregion

        public void Done()
        {
            m_isDone = true;
        }

        public bool IsComplete { get { return m_isDone; } }

        public abstract void Start();

        public void Initialize(Queue<EventItem> inputQueue, Queue<EventItem> resultQueue, ITask previous)
        {
            m_outputQueue = resultQueue;
            m_inputQueue = inputQueue;
            m_previous = previous;

            if (m_outputQueue == null)
            {
                throw new ArgumentNullException("resultQueue");
            }
        }

        protected void SetResult(params EventItem[] items)
        {
            foreach (var item in items)
            {
                lock (m_outputQueue)
                {
                    m_outputQueue.Enqueue(item);
                }
            }
        }

        protected EventItem GetItem()
        {
            while (true)
            {
                if (m_inputQueue == null)
                {
                    return null;
                }

                lock (m_inputQueue)
                {
                    if (m_inputQueue.Count == 0)
                    {
                        if (m_previous != null && m_previous.IsComplete)
                        {
                            return null;
                        }
                        else
                        {
                            System.Threading.Thread.Sleep(5000);
                            continue;
                        }
                    }
                    else
                    {
                        return m_inputQueue.Dequeue();
                    }
                }
            }
        }

        protected void RaiseProgress(int completed)
        {
            if (OnProgress != null)
            {
                OnProgress(this, ProgressEventArgs.EventArgs(completed));
            }
        }

        public virtual void Close() { }

        public event EventHandler<ProgressEventArgs> OnProgress;
    }

    public class ProgressEventArgs : EventArgs
    {
        private int _value;
        private ProgressEventArgs(int value)
        {
            _value = value;
        }

        public int Value { get { return _value; } }


        public static ProgressEventArgs EventArgs(int value)
        {
            return new ProgressEventArgs(value);
        }
    }
    
}
